/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
*
*
* Authors:                  zhoujian
* Email:            343600434@qq.com
* Date:         Jan-25-2024 11:03:03
*
*/

#include "FreeRTOS.h"


#include "uart_parse.h"
#include "stdio.h"
#include "Caige.h"
#include "input.h"
#include <string.h>
#include "jsm1302z.h"
#include "device.h"

//#define DEBUG_PRINTF

extern uint8_t display_no_idle;
uint8_t rx_buffer[BUFFER_SIZE];
volatile uint32_t rx_counter = 0;
volatile uint32_t rx_ok = 0;
MUSIC_T music_t;

PHONE_T phone_t;

uint8_t guidance_units, guide;
uint32_t Guide_distance;
uint8_t guide_update;
uint8_t guide_connected;
uint8_t guide_off;

uint8_t bk3288_hfp_connect = 0;
uint8_t music_on = 0;

uint8_t jihuo_t[7];

uint32_t lock_time;

void Guide_Data_Deal(uint8_t* p_buf)
{
    Guide_distance = (p_buf[16] << 24) + (p_buf[15] << 16) + (p_buf[14] << 8) + p_buf[13];

    if(Guide_distance > 999) {
        guidance_units = 0;    //km

    } else {
        guidance_units = 1;    //m
    }

#ifdef DEBUG_PRINTF
    log_debug("Guide_distance = %d %s\n", Guide_distance, ((guidance_units == 0) ? "km" : "m"));
#endif
    guide_off = 0;

    //      if(m > 100)
    //      Guide_distance = m/100;
    switch(p_buf[12]) {           //Next intersection direction
        case 1:
            guide = LEFT;
#ifdef DEBUG_PRINTF
            log_debug("left\n");
#endif
            break;      //left

        case 2:
            guide = RIGHT;
#ifdef DEBUG_PRINTF
            log_debug("right\n");
#endif
            break;       //right

        case 3:
            guide = LEFT_FRONT;
#ifdef DEBUG_PRINTF
            log_debug("left front\n");
#endif
            break;       //left front

        case 4:
            guide = RIGHT_FRONT;
#ifdef DEBUG_PRINTF
            log_debug("right front\n");
#endif
            break;       //right front

        case 5:
#ifdef DEBUG_PRINTF
            log_debug("left back\n");
#endif
            break;       //left back

        case 6:
            guide = RIGHT_BACK;
#ifdef DEBUG_PRINTF
            log_debug("right back\n");
#endif
            break;       //right back

        case 7:
            guide = TURN_LEFT;
#ifdef DEBUG_PRINTF
            log_debug("turn left \n");
#endif
            break;       //turn left

        case 8:
            guide = STRAIT;
#ifdef DEBUG_PRINTF
            log_debug("Straight travel\n");
#endif
            break;       //Straight travel

        case 13:
            guide_off = 1;

        default:
            break;
    }

    guide_update = 1;
    //if(guide_connected==0)guide_update=0;
}


uint16_t Ymodem_Protocol_Crc16(uint8_t* data, uint16_t len)
{
    uint32_t i;
    uint16_t crc = 0x0000;

    while(len--) {
        crc ^= (unsigned short)(*data++) << 8;

        for(i = 0; i < 8; ++i) {
            if(crc & 0x8000) {
                crc = (crc << 1) ^ 0x1021;

            } else {
                crc <<= 1;
            }
        }
    }

    return crc;
}


void parse_data_bug(char* buf, int total_len)
{
    int len = total_len;

    if(len >= 5) {
        if(rx_buffer[0] == 0x42) {
            if(rx_buffer[1] == 0x4b) {
                if(rx_buffer[2] == 0x46) {
                    if(len >= rx_buffer[3] + 4) {
                        if(rx_buffer[3] == 1) {
                            if(rx_buffer[4] == 0) {
                                BLUE_CON_OFF;

                            } else if(rx_buffer[4] == 1) {
                                BLUE_CON_ON;
                            }

                        } else {
                            if(rx_buffer[4] == MUSIC_INFO) {
                                //memset(music_t.blue_buf, 0, 256);
                                //memcpy(music_t.blue_buf, rx_buffer + 5, rx_buffer[3] - 1);
                            } else if(rx_buffer[4] == PHONE_INFO) {
                                memset(phone_t.blue_buf, 0, 32);
                                memcpy(phone_t.blue_buf, rx_buffer + 5, rx_buffer[3] - 1);

                                if(rx_buffer[3] != 2) {
                                    memset(phone_t.tel_num, 0, TEL_LEN);
                                    memcpy(phone_t.tel_num, rx_buffer + 5, rx_buffer[3] - 1);
                                    log_debug("%s\n", phone_t.tel_num);
                                }

                                if((rx_buffer[5] == PH_INCOM) || (PH_OUTGO == rx_buffer[5])) { //have phone
                                    //system("echo 1 169 1 > /sys/class/input/input1/phone");
                                    //bt_vol_open();
                                } else if(PH_HUNG == rx_buffer[5] || PH_DISCONN == rx_buffer[5]) { //end
                                    //bt_vol_close();
                                    //system("echo 1 169 0 > /sys/class/input/input1/phone");
                                }

                                //}else if(){
                                //} else if(rx_buffer[4] == TIMESTAMP_INFO) {
                                //      log_debug("timestamp=0x%02x%02x%02x%02x\n", rx_buffer[5], rx_buffer[6], rx_buffer[7], rx_buffer[8]);
                            }
                        }
                    }
                }
            }
        } else {
            if(len == 7) {
                if(rx_buffer[0] == 'C') {
                    if(rx_buffer[1] == 'o') {
                        if(rx_buffer[2] == 'n') {
                            if(rx_buffer[3] == 'n') {
                                if(rx_buffer[4] == 'e') {
                                    if(rx_buffer[5] == 'c') {
                                        if(rx_buffer[6] == 't') {
                                            ;//BLUE_KEY_ON;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

            } else if(len == 10) {
                if(rx_buffer[0] == 'D') {
                    if(rx_buffer[1] == 'i') {
                        if(rx_buffer[2] == 's') {
                            if(rx_buffer[3] == 'c') {
                                if(rx_buffer[4] == 'o') {
                                    if(rx_buffer[5] == 'n') {
                                        if(rx_buffer[6] == 'n') {
                                            if(rx_buffer[7] == 'e') {
                                                if(rx_buffer[8] == 'c') {
                                                    if(rx_buffer[9] == 't') {
                                                        ;//BLUE_KEY_OFF;
                                                    };
                                                };
                                            };
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

            } else {
                uint16_t tempdata;
                uint8_t i;

                for(i = 0; i < 20; i++) {
                    if(rx_buffer[i] == 0x24 && rx_buffer[i + 1] == 0x24) {
                        tempdata = (uint16_t)(rx_buffer[i + 18] << 8) + (uint16_t)rx_buffer[i + 17];
                        break;
                    }
                }

                if(i > 0) {
                    log_debug("uart receive error data %d", i);
                    return;

                } else if(Ymodem_Protocol_Crc16(rx_buffer, 17) == tempdata) {             //crc16Ð£Ñé
                    Guide_Data_Deal(rx_buffer + i);

                } else {
                    log_debug("tempdata=0x%x\n", tempdata);
                }
            }
        }
    }
}

uint8_t check_jihuo(uint8_t* buf)
{
    if(buf[0] == 0x50) {
        if(buf[7] == 0x1) {
            if(buf[8] == 0x1b) {
                if(buf[9] == 0x2) {
                    //if(jihuo_t[6] == 1||2==jihuo_t[6]){
                    if(is_lock_status == 0) {
#ifdef LOCK_IMMEDIATELY
                        //LOCK immediately
                        is_lock_status = 1;
                        // time_end = 1;
                        BLUE_KEY_ON;
                        lock_do();
#else

                        if(buf[11] == 0x2) {
                            //lock_do();
                            lock_time = (buf[12] - 0x30) * 10 + (buf[13] - 0x30);

                        } else if(buf[11] == 0x1) {
                            lock_time = buf[12] - 0x30;
                        }

#endif
                        jihuo_t[6] = 3;

                        if(bk3288_hfp_connect == 0) {
                            send_to_bk3288("\xEF", 1);
                        }
                    }

                } else if(buf[9] == 0x1) {
                    memcpy(jihuo_t, buf + 12, 6);

                    if(is_lock_status) {
                        jihuo_t[6] = 1;
                        is_lock_status = 0;
                        //BLUE_KEY_OFF;
                        //buf[12]~buf[17];
                        BLUE_KEY_OFF;
                        unlock_do();
                        log_debug("jihuo ok\n");
                    }

                    return 1;
                }
            }

        } else if(buf[7] == 0xF3) {
            log_debug("timestamp=0x%02x%02x%02x%02x%02x%02x%02x%02x\n", buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
            uint32_t h_tst = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | (buf[11]);
            uint32_t l_tst = (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | (buf[15]);
            uint64_t tst = (((uint64_t)(h_tst)) << 32 | (uint32_t)l_tst);
            log_debug("timestamp=0x%016llx\n", tst / 1000);
            //TimeStampToTime(tst / 1000);
            //TimeStampToTime();
        }
    }

    log_debug("jihuo error\n");
    return 0;
}

void parse_data(uint8_t* buf, int total_len)
{
    unsigned char* p;
    unsigned char len, index = 0;
    p = buf;

    if(total_len >= 4) {
        while(index < total_len) {
            p = buf + index;

            if(p[0] == 0x42) {
                if(p[1] == 0x4b) {
                    if(p[2] == 0x46) {
                        //sp_data.init = 1;
                        len = p[3];
                        //str_print(p, len+4);
#ifdef DEBUG_PRINTF
                        log_debug("\n:          parsed len=%d !!!\n", len);
#endif

                        //str_print(p+4, len);
                        if(len == 1) {
                            if((p[4] & 1) == 1) {
                                bk3288_hfp_connect = 1;
                                //BLUE_CON_ON;

                            } else if((p[4] & 1) == 0) {
                                bk3288_hfp_connect = 0;
                                //BLUE_CON_OFF;
                            }

                            if((p[4] & 6) == 6) {
                                music_on = 1;

                            } else if((p[4] & 6) == 0) {
                                music_on = 0;
                                //music_show_view = 0;
                            }

                            //switch(buf[4]){
#if 0
                            *((unsigned char*)&sp_data.init + 1) = p[4];

                            if(sp_data.conn == 0) {
                                //log_debug("00000000");
                                bt_vol_close();
                                pthread_mutex_lock(&music_mutex);
                                music_t.update = 1;
                                pthread_mutex_unlock(&music_mutex);
                                memset(music_t.blue_buf, 0, 256);

                            } else {
                                if(sp_data.play == 0) {
                                    //log_debug("00000000");
#if 0
                                    bt_vol_close();
                                    pthread_mutex_lock(&music_mutex);
                                    music_t.update = 1;
                                    pthread_mutex_unlock(&music_mutex);
#else

                                    if(sp_data.dac_on == 0) {
                                        //log_debug("00000000");
                                        bt_vol_close();
                                        pthread_mutex_lock(&music_mutex);
                                        music_t.update = 1;
                                        pthread_mutex_unlock(&music_mutex);
                                        //memset(music_t.blue_buf, 0, 256);

                                    } else {
                                        pthread_mutex_lock(&music_mutex);
                                        music_t.update = 1;
                                        pthread_mutex_unlock(&music_mutex);
                                        bt_vol_open();
                                    }

#endif
                                    //memset(music_t.blue_buf, 0, 256);

                                } else {
                                    pthread_mutex_lock(&music_mutex);
                                    music_t.update = 1;
                                    pthread_mutex_unlock(&music_mutex);
                                    bt_vol_open();
                                }
                            }

#endif

                        } else { //long protocol
                            if(p[4] == MUSIC_INFO) {
                                /*pthread_mutex_lock(&music_mutex);
                                music_t.update = 1;
                                pthread_mutex_unlock(&music_mutex);*/
                                //no display music
                                if(display_no_idle & 2) {
                                } else {
                                    music_t.update = 1;
                                    memset(music_t.blue_buf, 0, 256);
                                    memcpy(music_t.blue_buf, p + 5, len - 1);
                                    music_t.len = len - 1;
                                }

                            } else if(p[4] == PHONE_INFO) {
                                phone_t.update = 1;
                                memset(phone_t.blue_buf, 0, 32);
                                memcpy(phone_t.blue_buf, p + 5, len - 1);
                                log_debug("PHONE_INFO:%d\n", len);

                                if(len != 2) {
                                    phone_t.tel_update = 1;
                                    memset(phone_t.tel_num, 0, TEL_LEN);
                                    memcpy(phone_t.tel_num, p + 5, len - 1);
                                    //log_debug("tel:%s\n",phone_t.tel_num);
                                }

#if 1

                                if(phone_t.blue_buf[0] == PH_INCOM) {
                                    //log_debug("PH_INCOM \n");
                                    phone_t.tel_state = PH_INCOM;

                                } else if(PH_OUTGO == phone_t.blue_buf[0]) { //have phone
                                    // system("echo 1 169 1 > /sys/class/input/input1/phone");
                                    //bt_vol_open();
                                    //log_debug("PH_OUTGO \n");
                                    phone_t.tel_state = PH_OUTGO;

                                } else if(PH_HUNG == phone_t.blue_buf[0]) {
                                    //p/rintf("PH_HUNG\n");
                                    phone_t.tel_state = PH_HUNG;

                                } else if(PH_DISCONN == phone_t.blue_buf[0]) { //end
                                    //bt_vol_close();
                                    //system("echo 1 169 0 > /sys/class/input/input1/phone");
                                    //log_debug("PH_DISCONN\n");
                                    phone_t.tel_state = PH_DISCONN;
                                }

#endif

                            } else if(p[4] == GUIDE_INFO) {
                                uint16_t tempdata;
                                uint8_t i;

                                if(len == 8) {
                                    if(p[0 + 5] == 'C') {
                                        if(p[1 + 5] == 'o') {
                                            if(p[2 + 5] == 'n') {
                                                if(p[3 + 5] == 'n') {
                                                    if(p[4 + 5] == 'e') {
                                                        if(p[5 + 5] == 'c') {
                                                            if(p[6 + 5] == 't') {
                                                                //BLUE_KEY_ON;
                                                                guide_connected = 1;
                                                                log_debug("rec connected\n");
                                                                return;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }

                                } else if(len == 11) {
                                    if(p[0 + 5] == 'D') {
                                        if(p[1 + 5] == 'i') {
                                            if(p[2 + 5] == 's') {
                                                if(p[3 + 5] == 'c') {
                                                    if(p[4 + 5] == 'o') {
                                                        if(p[5 + 5] == 'n') {
                                                            if(p[6 + 5] == 'n') {
                                                                if(p[7 + 5] == 'e') {
                                                                    if(p[8 + 5] == 'c') {
                                                                        if(p[9 + 5] == 't') {
                                                                            //BLUE_KEY_OFF;
                                                                            guide_connected = 0;
                                                                            log_debug("rec disconnect\n");
                                                                            return;
                                                                        };
                                                                    };
                                                                };
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }

                                for(i = 0; i < 20; i++) {
                                    if(p[i + 5] == 0x24 && p[i + 1 + 5] == 0x24) { //ÕÒµ½±¨Í·ºÍ½áÊøÎ»
                                        tempdata = (uint16_t)(p[i + 18 + 5] << 8) + (uint16_t)p[i + 17 + 5];
                                        break;
                                    }
                                }

                                if(i > 0) {
                                    if(check_jihuo(p + 5)) {
                                        return;
                                    }

                                    log_debug("uart receive error data %d", i);
                                    return;

                                } else if(Ymodem_Protocol_Crc16(p + 5, 17) == tempdata) {         //crc16Ð£Ñé
                                    Guide_Data_Deal(&p[i + 5]);

                                } else {
                                    log_debug("tempdata=0x%x\n", tempdata);
                                }
                            }
                        }

                        index += len + 1;
                    }

                    index++;
                }

                index++;
            }

            index++;
        }
    }
}

void uart0_send(char* buf, int len)
{
    do {
        usart_data_transmit(COMMU_COM, *(uint8_t*)buf++);
        len--;

        while(RESET == usart_flag_get(COMMU_COM, USART_FLAG_TC));
    } while(len);
}

void send_to_bk3288(char* buf, int len)
{
#ifdef DEBUG_PRINTF
    unsigned char i;
    log_debug((const char*)"s: ----> ");
    log_debug((const char*)"0x46 0x42 0x4b ");
    log_debug("0x%02x ", len);

    for(i = 0; i < len * 2; i += 2) {
        log_debug("0x%01x", buf[i] >> 4);
        log_debug("%01x ", buf[i] & 0xF);
    }

    log_debug("\n");
#endif
    uart0_send("\x46\x42\x4b", 3);
    uart0_send((char*)&len, 1);
    uart0_send(buf, len);
    /*while(i)
    {
        if(REG_UART1_FIFO_STATUS & MSK_UART1_FIFO_STATUS_FIFO_WR_READY)
        {
            REG_UART1_FIFO_PORT = *p++;
            i--;
        }
    }
    //uart1_send(buf, len);
    while(len)
    {
        if(REG_UART1_FIFO_STATUS & MSK_UART1_FIFO_STATUS_FIFO_WR_READY)
        {
            REG_UART1_FIFO_PORT = *buf++;
            len--;
        }
    }*/
    //send head and len
}


void uart_recv(void)
{
    int8_t len, i;

    if(1 == rx_ok) {
        rx_ok = 0;

    } else {
        if(rx_counter > 0) {
            len = rx_counter;
            rx_counter = 0;
#ifdef DEBUG_PRINTF
            log_debug("@ len= %d\n", len);

            for(i = 0; i < len; i++) {
                log_debug("0x%01x", rx_buffer[i] >> 4);
                log_debug("%01x ", rx_buffer[i] & 0xF);
                //log_debug("%c", rx_buffer[i]);
            }

#endif
            parse_data(rx_buffer, len);
        }
    }
}

